#include <cv.h>
#include <highgui.h>
#include "abstractProbabilityTransformer.hpp"
#include "abstractFilter.hpp"
#include "resourceTracker.h"
#include "faceDetector.h"
#include "AbstractHandTracker.hpp"
#include "HIVideoCapture.hpp"
#include "handLocaliser.hpp"

#include "AbstractHandTrackerTest.hpp"
#include "HandTrackerLKGREYwMSwBPwBGESwFOx.hpp"

#include <iostream>
//TODO clean up includes

//this looks up the location of the gtest files in header hiDependenciesForTestFramework.h
//TODO : Design choice? currently I'll keep this dependency in a very specific header file
// as changing it should cause minimal recompilation.

#include "gtest.h"

//NOTE: hiDependenciesForTestFramework also sets HI_TEST_VISUALISATION
//which if set will make tests compile to show images of the things they test.

//FIXNOW: normalise error according to tracking rect size? (include both normalised and raw error)

using namespace cv;

class HandTrackerLKGREYwMSwBPwBGESwFOxTest : public ::AbstractHandTrackerTest {
protected:
	void setHandTracker(int trackerCode);
};


// -- test case codes -- //
#define A0B10FO0 -10
#define A0B10FO1 -11
#define A0B10FO2 -12

#define A5B5FO0 0
#define A5B5FO1 1
#define A5B5FO2 2

#define A8B5FO0 10
#define A8B5FO1 11
#define A8B5FO2 12

#define A8B8FO0 20
#define A8B8FO1 21
#define A8B8FO2 22

#define A8B10FO0 30
#define A8B10FO1 31
#define A8B10FO2 32


void HandTrackerLKGREYwMSwBPwBGESwFOxTest::setHandTracker(int trackerCode) {
	
	switch ( trackerCode ) {
		//Regular: just past frame
		case A0B10FO0:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(0)), 0.0, 1.0 );
			break;
		case A0B10FO1:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(1)), 0.0, 1.0 );
			break;
		case A0B10FO2:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(2)), 0.0, 1.0 );
			break;
			
		// half half
		case A5B5FO0:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(0)), 0.5, 0.5 );
			break;
		case A5B5FO1:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(1)), 0.5, 0.5 );
			break;
		case A5B5FO2:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(2)), 0.5, 0.5 );
			break;
			
		//saturate
		case A8B5FO0:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(0)), 0.8, 0.5  );
			break;
		case A8B5FO1:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(1)), 0.8, 0.5  );
			break;
		case A8B5FO2:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(2)), 0.8, 0.5  );
			break;
			
		//saturate fast
		case A8B8FO0:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(0)), 0.8, 0.8  );
			break;
		case A8B8FO1:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(1)), 0.8, 0.8  );
			break;
		case A8B8FO2:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(2)), 0.8, 0.8  );
			break;

		
		//saturate very fast
		case A8B10FO0:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(0)), 0.8, 1.0  );
			break;
		case A8B10FO1:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(1)), 0.8, 1.0  );
			break;
		case A8B10FO2:
			ht = HandTrackerLKGREYwMSwBPwBGESwFOx::init(
												   hl->getProbabilityTransformer(), trackingRect, frame,
												   Ptr< AbstractFilter >(new OpenFilter(2)), 0.8, 1.0  );
			break;
			
		default:
			ASSERT_TRUE(false);
			break;
	}
}



TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a0b10fo0locVid1c ) {
	testTracker( A0B10FO0, "locVid1c" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a0B10FO1locVid1c ) {
	testTracker( A0B10FO1, "locVid1c" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a0B10FO2locVid1c ) {
	testTracker( A0B10FO2, "locVid1c" );
}


TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a5B5FO0locVid1c ) {
	testTracker( A5B5FO0, "locVid1c" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a5B5FO1locVid1c ) {
	testTracker( A5B5FO1, "locVid1c" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a5B5FO2locVid1c ) {
	testTracker( A5B5FO2, "locVid1c" );
}


TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B5FO0locVid1c ) {
	testTracker( A8B5FO0, "locVid1c" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B5FO1locVid1c ) {
	testTracker( A8B5FO1, "locVid1c" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B5FO2locVid1c ) {
	testTracker( A8B5FO2, "locVid1c" );
}


TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B8FO0locVid1c ) {
	testTracker( A8B8FO0, "locVid1c" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B8FO1locVid1c ) {
	testTracker( A8B8FO1, "locVid1c" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B8FO2locVid1c ) {
	testTracker( A8B8FO2, "locVid1c" );
}


TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B10FO0locVid1c ) {
	testTracker( A8B10FO0, "locVid1c" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B10FO1locVid1c ) {
	testTracker( A8B10FO1, "locVid1c" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B10FO2locVid1c ) {
	testTracker( A8B10FO2, "locVid1c" );
}



TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a0b10fo0TrackerTest1 ) {
	testTracker( A0B10FO0, "TrackerTest1" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a0B10FO1TrackerTest1 ) {
	testTracker( A0B10FO1, "TrackerTest1" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a0B10FO2TrackerTest1 ) {
	testTracker( A0B10FO2, "TrackerTest1" );
}


TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a5B5FO0TrackerTest1 ) {
	testTracker( A5B5FO0, "TrackerTest1" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a5B5FO1TrackerTest1 ) {
	testTracker( A5B5FO1, "TrackerTest1" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a5B5FO2TrackerTest1 ) {
	testTracker( A5B5FO2, "TrackerTest1" );
}


TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B5FO0TrackerTest1 ) {
	testTracker( A8B5FO0, "TrackerTest1" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B5FO1TrackerTest1 ) {
	testTracker( A8B5FO1, "TrackerTest1" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B5FO2TrackerTest1 ) {
	testTracker( A8B5FO2, "TrackerTest1" );
}


TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B8FO0TrackerTest1 ) {
	testTracker( A8B8FO0, "TrackerTest1" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B8FO1TrackerTest1 ) {
	testTracker( A8B8FO1, "TrackerTest1" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B8FO2TrackerTest1 ) {
	testTracker( A8B8FO2, "TrackerTest1" );
}


TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B10FO0TrackerTest1 ) {
	testTracker( A8B10FO0, "TrackerTest1" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B10FO1TrackerTest1 ) {
	testTracker( A8B10FO1, "TrackerTest1" );
}

TEST_F(HandTrackerLKGREYwMSwBPwBGESwFOxTest, a8B10FO2TrackerTest1 ) {
	testTracker( A8B10FO2, "TrackerTest1" );
}